#include "ShpUtil.h"
#include "GDALCPP.h"
#include "OCMain/FileUtil.h"

//namespace OCPP
//{
//	template <typename T>
//	Feature& Feature::set_field(const char* name, T&& arg) {
//		m_feature->SetField(name, std::forward<T>(arg));
//		return *this;
//	}
//}

namespace OCPP
{
	const String driver_name = "ESRI Shapefile";

	static point_type create_point(Vector2 point) {
		OGRPoint* p = (OGRPoint*)OGR_G_CreateGeometry(wkbPoint);
		p->setX(point.x);
		p->setY(point.y);
		return point_type{ p };
	}

	static linestring_type create_linestring(Vector2List points) {
		OGRLineString* geom = (OGRLineString*)OGR_G_CreateGeometry(wkbLineString);
		for (auto p : points)
		{
			geom->addPoint(p.x, p.y);
		}
		return linestring_type{ geom };
	}

	static ring_type create_ring(Vector2List points) {
		OGRLinearRing* geom = (OGRLinearRing*)OGR_G_CreateGeometry(wkbLinearRing);
		for (auto p : points)
		{
			geom->addPoint(p.x, p.y);
		}
		return ring_type{ geom };
	}

	static polygon_type create_polygon(Vector2List points) {
		OGRPolygon* p = (OGRPolygon*)OGR_G_CreateGeometry(wkbPolygon);
		ring_type ring = create_ring(points);
		p->addRingDirectly(ring.release());
		return polygon_type{ p };
	}

	ShpUtil::ShpUtil()
	{

	}

	ShpUtil::~ShpUtil()
	{
		
	}


	void ShpUtil::deleteShpfile(String fileName)
	{
		String ext = FileUtil::getFileExtension(fileName);
		if (ext == "shp")
		{
			String name = StringUtil::replaceAll(fileName,".shp","");
			FileUtil::deleteFile(fileName);
			FileUtil::deleteFile(name + ".dbf");
			FileUtil::deleteFile(name + ".prj");
			FileUtil::deleteFile(name + ".shx");
		}
	}

	void ShpUtil::writePoint(String fileName, Vector2 points)
	{
		String name, ext, path;
		StringUtil::splitFullFilename(fileName, name, ext, path);
		try {
			Dataset dataset{ "GeoJSON", fileName, SRS{4326}, {}};

			Layer layer{ dataset ,name, wkbPoint };
			layer.add_field("id", OFTInteger, 7);
			Feature feature{ layer,create_point(points) };
			feature.set_field("id", int(2));
			feature.add_to_layer();
		}
		catch (gdal_error e) {
			std::cout << String{ "creating feature in layer '" } + "' failed" << "\n";
		}
	}

	void ShpUtil::writeLine(String fileName, Vector2List points)
	{
		try {
			Dataset dataset{ driver_name, FileUtil::getFilePath(fileName), SRS{4326}, {} };

			Layer layer{ dataset ,"line", wkbLineString };
			layer.add_field("id", OFTInteger, 7);
			Feature feature{ layer,create_linestring(points) };
			feature.set_field("id", int(2));
			feature.add_to_layer();
		}
		catch (gdal_error e) {
			std::cout << String{ "creating feature in layer '" } + "' failed" << "\n";
		}
	}

	void ShpUtil::writePolygon(String fileName, Vector2List points)
	{
		try {
			Dataset dataset{ driver_name, FileUtil::getFilePath(fileName), SRS{4326}, {} };

			Layer layer{ dataset ,"polygon", wkbPolygon };
			layer.add_field("id", OFTInteger, 7);
			Feature feature{ layer,create_polygon(points) };
			feature.set_field("id", int(2));
			feature.add_to_layer();
		}
		catch (gdal_error e) {
			std::cout << String{ "creating feature in layer '" } + "' failed" << "\n";
		}
	}
}
